package ecs.core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class Entity implements IEntity {

    private final HashMap<Class<?>, IComponent> _components;

    public Entity()
    {
        _components = new HashMap<>();
    }

    @Override
    public <T extends IComponent> void add(T component) {
        _components.put(component.getClass(), component);
        component.parent(this);
    }

    @Override
    public void remove(Class<?> type) {
        IComponent component = _components.remove(type);
        if(component != null) component.parent(null);
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T extends IComponent> T component(Class<T> type) {
        IComponent component = _components.get(type);
        return component==null? null: (T)_components.get(type);
    }

    @Override
    public List<IComponent> components(Class<?>... types) {
        List<IComponent> components = new ArrayList<>();
        for (Class<?> type : types) {
            if(_components.containsKey(type))
            {
                components.add(_components.get(type));
            }
            else
            {
                components.clear();
                break;
            }
        }
        return components;
    }

    @Override
    public List<IComponent> components() {
        return _components.values().stream().toList();
    }

    @Override
    public <T extends IComponent> boolean has(Class<T> type) {
        return _components.containsKey(type);
    }

    @Override
    public boolean hasAll(Class<?>... types) {
        boolean flag = true;
        for (Class<?> type : types) {
            if(!_components.containsKey(type))
            {
                flag = false;
                break;
            }
        }
        return flag;
    }

    public static boolean Enables(List<IComponent> components)
    {
        boolean flag = true;
        for (IComponent component : components) {
            if(!component.enable())
            {
                flag = false;
                break;
            }
        }
        return flag;
    }

}
